package com.hxk.jvm;

import java.util.ArrayList;
import java.util.List;

/**
 * jvm是什么？
 *      jvm是java虚拟机，主要负责java类的加载，运行和底层系统语言调用
 * 1、jvm的类加载器有几种：
 *      1、Bootstrap：启动类加载器C++, 这里加载的是JAVA_HOME/jre/lib/rt.jar（Object、ArrayList等）
 *      2、ExtClassLoader：扩展类加载器Java，加载的是JAVA_HOME/jre/lib/ext/*.jar的所以jar包（Swing）
 *      3、AppClassLoad：应用程序类加载器 java，系统ClassPath的所有类
 *      4、UserClassLoad：用户自定义类加载器
 *      jvm的类加载顺序是：不管加载任何类都是先从BootstrapLoad->ExtClassLoader->AppClassLoad如果在这3个类加载器任意一个找到，直接运行，如果找不到要加载的类，则报ClassNotFoundException异常。
 *          jvm的类加载过程使用类双亲委派机制从而保证沙箱安全
 * 2、native方法栈区：
 *      2.1、native调用底层c语言函数库
 * 3、程序计算器（pc寄存器）
 *      3.1、主要负责程序内部的运行流程和跳转顺序（类似排班值日表）
 * 4、方法区
 *      4.1：存放类模版（就是ClassLoad加载xxx.class后变成的Class对象）、静态变量都存储在方法区
 * 5、栈（stack）区：
 *      5.1：程序要运行，需要申请栈空间，程序运行结束立即释放。
 *      5.2：栈区主要存储，java中8种基本类型变量+引用类型变量+实例方法都存放在这里
 *      5.3：这里如果出现代码递归调用，会出现SOF(StackOverFlowError错误异常)
 * 6、堆（heap）区：
 *      6.1：需要垃圾回收的区域
 *      6.2：主要存储实例对象
 *      6.3：堆区按物理分类被分为：新生区（Yang|New）和老年区（Old）
 *      6.4: 按逻辑上分类被分为：新生区（Yang|New）、老年区（Old）和永久区（元空间）
 *      6.5：新生区又分为：伊甸原区（Eden）、幸存者0区（From区）和幸存者1区（To区），他们的分配比例为8比1比1
 *      6.5.1：当伊甸原区满了之后会执行第一次GC（YGC）操作，清空Eden区，将幸存者复制到From区，
 *              当eden区在满了，第二次GC，将之前一直存活的对象复制到To区域，然后这样反复交换，
 *              如果对象能存活15次，将会把对象存储到老年区，
 *      6.5.2：当老年区满了，会执行GC（FGC），如果gc后发现没有要清除的对象，这时会报OOM（OutOfMemoryError错误异常）
 *      永久区（元空间）：1.8使用的是物理内存
 *             rt.jar的类都加载里面，String常量池
 *
 */
public class JVMCase {
    public static void main(String[] args) {
        //类加载代码事例
        //注意bootstrap类加载器在这里是Null
        Object object = new Object();
        System.out.println(object.getClass().getClassLoader());

        JVMCase jvmCase = new JVMCase();
        System.out.println(jvmCase.getClass().getClassLoader().getParent().getParent());
        System.out.println(jvmCase.getClass().getClassLoader().getParent());
        System.out.println(jvmCase.getClass().getClassLoader());

        //native代码事例thread.start()的底层调用的是native Start0()方法
        Thread thread = new Thread();
        thread.start();

        //引发SOF的代码事例
        //jvmCase.m1();

        //引发OOM的代码事例
        List<byte[]> datas = new ArrayList<byte[]>();
        while ( true ) {
            datas.add(new byte[1024 * 1024]);
        }
    }

    //该方法的所有运行过程在jvm的栈区
    private int add(int a, int b){
        int res = 1;
        res = a + b;
        return res;
    }

    public void m1(){
        m1();
    }
}
